/***************************************************************************

    MapCG: MapReduce Framework for CPU & GPU

    Copyright (C) 2010, Chuntao HONG (Chuntao.Hong@gmail.com).

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

**************************************************************************/

#ifndef MAPREDUCE_H
#define MAPREDUCE_H

#include <stdio.h>
/*
#if defined(HMMHASHTABLECPU_H)
#define HMM_FUNC HMMSchedulerCPU:: 
#include "HMM/CPULib/HMMHashTableCPU.h"
namespace HMM_CPU{
#elif defined(HMMHASHTABLEGPU_H)
#define HMM_FUNC __device__
#include "HMM/GPULib/HMMHashTable.h"
namespace HMM_GPU{
#endif
*/

#ifdef __CUDACC__
#define HMM_FUNC __device__
#include "HMM/GPULib/HMMHashTable.h"
namespace HMM_GPU {
#else
#define HMM_FUNC HMMSchedulerCPU::
#include "HMM/CPULib/HMMHashTableCPU.h"
namespace HMM_CPU {
#endif

void HMM_FUNC slice(const void * input_array, const unsigned int data_size, 
				const unsigned int unit_size, const unsigned int index, 
				const void * &ret_ptr, unsigned int & ret_size){
	default_slice(input_array, data_size, unit_size, index, ret_ptr, ret_size);
}

void HMM_FUNC map(const void * ptr, const unsigned int size, const global_data_t & global_data)
{
	SBUN * relation = global_data.r;
	unsigned int * offsets = (unsigned int*)ptr;
	int numRecords = size / sizeof(int);
	for(int i = 0; i < numRecords; ++i)
	{
		SBUN & r = *(relation + offsets[i]);
		emit_intermediate(&(r.key), sizeof(int), &r, sizeof(SBUN));
	}
}

void HMM_FUNC map_2(const void * ptr, const unsigned int size, const global_data_t & global_data, HashMultiMap * old_hash_table)
{
	SBUN * relation = global_data.s;
	unsigned int * offsets = (unsigned int*)ptr;
	int numRecords = size / sizeof(int);
	for (int i = 0; i < numRecords; ++i)
	{
		SBUN & s = *(relation + offsets[i]);
		// get the linked list for this value
		ValueList * vList = old_hash_table->getBucketFromKey(&(s.key), sizeof(int)).getValueListNoMalloc(&(s.key), sizeof(int));
		// if there is anything in the list
		if (vList != NULL)
		{
			// get the first node
			ValueListNode * curr = vList->head;

			// while the current node is not null
			while (curr != NULL)
			{
				// get the actual item out of the node
				const void * r;
				unsigned int size;
				curr->getValue(r, size);
				// emit the payloads of r and s
				SBUN out;
				out.key = ((const SBUN *)r)->payload;
				out.payload = s.payload;
				emit_intermediate(&(s.key), sizeof(int), &out, sizeof(SBUN));
				// advance to the next node
				curr = curr->next;
			}
		}
	}
}

void HMM_FUNC reduce(HMMKVs_t & kv, const global_data_t & global_data)
{
	// no code here because it doesn't get run
}

void HMM_FUNC combine(void * old_val, const void * new_val){

}

};
#endif
